#include "cnet.h"
#include "log.h"
using namespace yssdk;
CNet::CNet( int maxclient, int port):m_acceptor(m_ioservice, ip::tcp::endpoint( ip::tcp::v4(), port))
{
    m_maxclient = maxclient;
    for(int i=0; i< m_maxclient; i++)
    {
        CConnectHandl* socket =new CConnectHandl(this,i,m_ioservice);
        m_ConnectHandl_Pool.push_back(socket);
        pushUID(i);
    }
}

void CNet::pushUID(int uid)
{
    m_socket_GUID_mutex.lock();
    m_GUID_Pool.push(uid);
    m_socket_GUID_mutex.unlock();
}



int CNet::popUID()
{
    int uid=-1;
    if(!m_GUID_Pool.empty())
    {
        m_socket_GUID_mutex.lock();
        uid=m_GUID_Pool.front ();
        m_GUID_Pool.pop();
        m_socket_GUID_mutex.unlock();

    }
    return uid;
}

CConnectHandl* CNet::GetUidHandle(int uid)
{
    if(uid>=m_ConnectHandl_Pool.size()||uid<0)
        return NULL;
    return m_ConnectHandl_Pool[uid];
}

void CNet::accept()
{
    CConnectHandl* psocket=NULL;
    int uid=popUID();
    psocket=GetUidHandle(uid);
    if(psocket!=NULL)
    {
        psocket->ZeroBuffer();
        m_acceptor.async_accept(*psocket,boost::bind(&CNet::accept_handler, this, psocket, _1));
    }
}

void CNet::accept_handler(CConnectHandl* psocket,error_code ec)
{
    if(ec)
        return;
    psocket->readIo();
    accept();
}

bool CNet::Run(int ThreadNum)
{
    accept();
    boost::thread_group work;
    for(int i=0;i<ThreadNum;i++)
    {
        work.create_thread(boost::bind(&boost::asio::io_service::run,&m_ioservice));
    }
    return true;
}

void CNet::sendMessage(int guid, Message *msg)
{
   CConnectHandl* handle= GetUidHandle(guid);
   m_ioservice.post(boost::bind(&CNet::sendpostcomplete ,this,handle,msg));
}
void CNet::sendpostcomplete(CConnectHandl* handle ,Message *msg)
{
    handle->SendIo (msg);
}

void CNet::closePostcomplete(CConnectHandl *handle)
{
    handle->close ();
    pushUID (handle->UID);
}
void CNet::closeConnectHandl(int guid)
{
    CConnectHandl* handle= GetUidHandle(guid);
    m_ioservice.post(boost::bind(&CNet::closePostcomplete ,this,handle));
}
